package top.ucat.boots.starter.oauth2.server.factory;

import lombok.extern.slf4j.Slf4j;
import top.ucat.boots.common.check.Assert;
import top.ucat.boots.common.exception.BaseException;
import top.ucat.boots.starter.db.annotation.Db;
import top.ucat.boots.starter.oauth2.client.beans.oauth.OauthToken;
import top.ucat.boots.starter.oauth2.client.beans.oauth.SystemUser;
import top.ucat.boots.starter.oauth2.client.beans.oauth.login.PhoneVerLoginDto;
import top.ucat.boots.starter.oauth2.client.definition.UserCodeTypeDefinition;
import top.ucat.boots.starter.oauth2.client.entity.OauthClientDetails;
import top.ucat.boots.starter.oauth2.client.entity.OauthUserCredentials;
import top.ucat.boots.starter.oauth2.client.realm.AuthorizingRealm;
import top.ucat.boots.starter.oauth2.client.service.api.ClientService;
import top.ucat.boots.starter.oauth2.client.service.api.TokenService;
import top.ucat.boots.starter.oauth2.server.factory.base.LoginFactory;

@Slf4j
public class PhoneVerificationCodeSsoFactory implements LoginFactory {

    private static PhoneVerificationCodeSsoFactory verificationCodeSsoFactory;
    private DefaultLoginFactory defaultLoginFactory;
    private AuthorizingRealm authorizingRealm;
    private TokenService tokenService;
    private ClientService clientService;

    public void setAuthorizingRealm(AuthorizingRealm authorizingRealm) {
        this.authorizingRealm = authorizingRealm;
    }

    public void setTokenService(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    public void setClientService(ClientService clientService) {
        this.clientService = clientService;
    }

    public static PhoneVerificationCodeSsoFactory getInstance() {
        return verificationCodeSsoFactory;
    }

    public PhoneVerificationCodeSsoFactory() {
    }

    private PhoneVerificationCodeSsoFactory(DefaultLoginFactory defaultLoginFactory) {
        this.defaultLoginFactory = defaultLoginFactory;
    }

    public static PhoneVerificationCodeSsoFactory getInstance(DefaultLoginFactory defaultLoginFactory) {
        if (verificationCodeSsoFactory == null) {
//            Class classs = VerificationCodeSsoFactory.class;
            synchronized (PhoneVerificationCodeSsoFactory.class) {
                if (verificationCodeSsoFactory == null) {
                    verificationCodeSsoFactory = new PhoneVerificationCodeSsoFactory(defaultLoginFactory);
                }
            }
        }
        return verificationCodeSsoFactory;
    }

    public OauthUserCredentials getUserCredentials(String userCode, String userCodeType, String systemType) {
        return this.defaultLoginFactory.getUserCredentials(userCode, userCodeType, systemType);
    }

    public OauthUserCredentials registerUserCredentials(String userId, String userCode, String userCodeType, String systemType) {
        return this.defaultLoginFactory.registerUserCredentials(userId, userCode, userCodeType, systemType);
    }

    public OauthUserCredentials registerUserCredentials(String userId, String userCode, String userCodeType, String systemType, boolean isCheck) {
        return this.defaultLoginFactory.registerUserCredentials(userId, userCode, userCodeType, systemType, isCheck);
    }

    @Deprecated
    public Object registerUser(String userId, String userCode, String userCodeType, String systemType) {
        OauthUserCredentials userCredentials = this.getUserCredentials(userCode, userCodeType, systemType);
        if (userCredentials != null) {
        }
        throw new BaseException("创建用户登录凭证失败", 400);
    }

    public OauthToken login(PhoneVerLoginDto dto) {
        Assert.isNotNull(this.clientService, "clientService missing", 400);
        OauthClientDetails client = this.clientService.getClient(dto.getClientId(), dto.getClientSecret());
        String phoneNum = dto.getPhoneNum();
        log.debug("用户标识:[{}]", phoneNum);
        Assert.isNotEmpty(phoneNum, "用户电话号码不能为空", 400);
        OauthUserCredentials userCredential = this.getUserCredentials(phoneNum, UserCodeTypeDefinition.phoneVerificationCode, dto.getSystemType());
        Assert.isNotNull(userCredential, "找不到用户凭证", 400);
        Assert.isNotNull(this.authorizingRealm, "authorizingRealm missing", 500);
        SystemUser systemUser = this.authorizingRealm.getSystemUser(userCredential);
        Assert.isNotNull(systemUser, "用户不存在", 400);
        systemUser.setUserId(userCredential.getUserId());
        systemUser.setUserCode(phoneNum);
        systemUser.setSystemType(dto.getSystemType());
        systemUser.setUserCodeType(UserCodeTypeDefinition.phoneVerificationCode);
        Assert.isNotNull(this.tokenService, "tokenService missing", 400);
        OauthToken accessToken = this.tokenService.createLoginAccessToken(client, systemUser, dto.isRetainToken());
        return accessToken;
    }
}